npm i的具体机制
- 早期的时候 是严格按照
package.json
的结构,一一对应的在node_modules
中按照对应的包,这样造成的问题就是:- 嵌套层级可能过深,在
Windows
系统中,文件路径最大长度为260个字符 - 重复的安装包
- 嵌套层级可能过深,在
- 后来
npm 3.X
版本采用扁平化的结构- 安装模块时,不管其是直接依赖还是子依赖的依赖,优先将其安装在
node_modules
根目录。 - 当安装到相同模块时,判断已安装的模块版本是否符合新模块的版本范围,如果符合则跳过,不符合则在当前模块的
node_modules
下安装该模块。npm 3.x
版本并未完全解决老版本的模块冗余问题,甚至还会带来新的问题。package.json
通常只会锁定大版本,这意味着在某些依赖包小版本更新后,同样可能造成依赖结构的改动,依赖结构的不确定性可能会给程序带来不可预知的问题。
- 安装模块时,不管其是直接依赖还是子依赖的依赖,优先将其安装在
- 为了解决
npm install
的不确定性问题,在npm 5.x
版本新增了package-lock.json
文件,而安装方式还沿用了npm 3.x
的扁平化的方式。package-lock.json
的作用是锁定依赖结构,即只要你目录下有package-lock.json
文件,那么你每次执行npm install
后生成的node_modules
目录结构一定是完全相同的。- 这里注意,并不是所有的子依赖都有
dependencies
属性,只有子依赖的依赖和当前已安装在根目录的node_modules
中的依赖冲突之后,才会有这个属性。
npm i的整体流程
检查有无lock文件——》无lock文件,构建依赖树——》不管直接依赖还在子依赖,直接扁平化结构都放在node_modules目录下,遇到相同模块时,判断已安装的模块版本是否符合新模块版本,符合跳过,不符合则在当前模块的node_modules下放置该模块,注意这一步只是逻辑上的确定依赖树,并不是真正的安装——》在缓存中查找依赖树对应的包,不存在则去npm仓库拉取依赖包,校验包的完整性,不完整就重新下载。下载包成功后解压到node_modules下。——》生成lock文件
检查有无lock文件——》有lock文件,判断package.json文件的依赖版本是否与package-lock.json文件中的依赖有冲突;——》没有冲突直接跳过拉取包,确定依赖树的过程,直接解压包到node_modules中